package com.googlecode.afdbaccess.web.common.servletfilter.sessionlesscookieauthentication;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.HashSet;

import com.googlecode.afdbaccess.web.common.login.ApplicationPrincipal;

class SerializeableUserInfo {
    private final static int SERIALIZATION_VERSION = 1;
    
    private ApplicationPrincipal principal = null;
    private HashSet<String> roles = null;
    private long timestamp = System.currentTimeMillis();
    
    SerializeableUserInfo(ApplicationPrincipal principal, HashSet<String> roles) {
        this.principal = principal;
        this.roles = roles;
    }

    boolean isFresh(int loginValidForMinutes) {
        if (System.currentTimeMillis()-timestamp <= loginValidForMinutes*60*1000) {
            return true;
        } else {
            return false;
        }
    }

    ApplicationPrincipal getPrincipal() {
        return this.principal;
    }

    HashSet<String> getRoles() {
        return this.roles;
    }

    byte[] toBytes() throws IOException {
        // TODO: escape newlines
        
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            PrintWriter pw = new PrintWriter(baos);
            try {
                pw.println(SERIALIZATION_VERSION);
                pw.println(timestamp);
                pw.println(principal.getName());
                pw.println(principal.getDisplayName());
                pw.println(principal.getUserId());
                
                pw.println(roles.size());
                
                for (String role : roles) {
                    pw.println(role);
                }
            } finally {
                pw.close();
            }
            
            return baos.toByteArray();
        } finally {
            baos.close();
        }
    }

    public static SerializeableUserInfo fromBytes(byte[] bytes) throws NumberFormatException, IOException {
        // TODO: unescape newlines

        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(bais));
            
            try {
                int version = Integer.parseInt(br.readLine());
                
                if (version != SERIALIZATION_VERSION) {
                    throw new IOException("Bad version number. Got " + version + ", excepted " + SERIALIZATION_VERSION);
                }

                long timestamp = Long.parseLong(br.readLine());
                String name = br.readLine();
                String displayName = br.readLine();
                long userId = Long.parseLong(br.readLine());
                
                int rolesSize = Integer.parseInt(br.readLine());
                
                HashSet<String> roles = new HashSet<String>();
                
                for (int roleCounter = 0; roleCounter < rolesSize; roleCounter++) {
                    roles.add(br.readLine());
                }

                SerializeableUserInfo encryptedUserInfo = new SerializeableUserInfo(new ApplicationPrincipal(name, userId, displayName), roles);
                encryptedUserInfo.timestamp = timestamp;
                
                return encryptedUserInfo;
            } finally {
                br.close();
            }
        } finally {
            bais.close();
        }
    }  
}
